﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Dataweb.NShape;
using cz.zcu.PreSti.Shapes;

namespace cz.zcu.PreSti.Guide
{
    /// <summary>
    /// Represents random type of guide.
    /// </summary>
    public class SequentialGuide : GuideParent
    {		
        //Variables
		private int shapePossitionX = 250;
        private Boolean exception = false;

        /// <summary>
        /// Initializes a new instance of the <see cref="SequentialGuide"/> class.
        /// </summary>
        /// <param name="project">The project.</param>
        /// <param name="diagram">The diagram.</param>
        /// <param name="listProperties">The list properties.</param>
        /// <param name="window">The window.</param>
        public SequentialGuide(Project project, Diagram diagram, List<Property> listProperties, Form window)
		{
            InitializeParametres(project, diagram, listProperties, window);
            cbAlignmentH.SetBounds(194,  94, 133,28);
            cbAlignmentV.SetBounds(194, 128, 133, 28);
            btPath.SetBounds(355, 63, 58, 26);
			EventsRegistration();
            LoadPage1();
        }

        /// <summary>
        /// Registrates the events to the controls.
        /// </summary>
		private void EventsRegistration()
		{
			listbox.Click += listbox1_Click; 
			checkBox.CheckedChanged += CBHelp_CheckedChanged;
			cbAlignmentH.Click += TextBoxs_Leave;
			cbAlignmentV.Click += TextBoxs_Leave;
            cbAlignmentH.SelectedIndexChanged += CB_SelectedIndexChanged;
            cbAlignmentV.SelectedIndexChanged += CB_SelectedIndexChanged;
            btAdd.Click += BTAdd_Click;
			TextsBoxesEventRegistration();
			btDelete.Click += BT_Delete;
            gbProperties.MouseLeave += GB_Mouse_Leave;
            btPath.Click += BTPath_Click;
		}

        /// <summary>
        /// Handles the Click event of the BTPath control: provides a possibility to enter path of image from operation system.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void BTPath_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();

            if (ofd.ShowDialog() == DialogResult.OK)
            {
                listProperties[1].TextBox.Text = ofd.FileName;
            }
        }

        /// <summary>
        /// Handles the Leave event of the GB_Mouse control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void GB_Mouse_Leave(object sender, EventArgs e)
        {
            if (listbox.SelectedItem != null)
            {
                if (exception == false)
                {
                    TextBoxs_Leave(new object(), new EventArgs());                    
                }
            }
        }

        /// <summary>
        /// Handles the Click event of the BTAdd control: adds stimuli to the shape list.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void BTAdd_Click(object sender, EventArgs e)
        {
            AddStimuli(cbStimuliType.SelectedItem.ToString());
        }

        /// <summary>
        /// The Event registration of text boxes.
        /// </summary>
        private void TextsBoxesEventRegistration()
		{
			for (int i = 0; i < listProperties.Count; i++)
			{
				listProperties[i].TextBox.Leave += TextBoxs_Leave;
			}
		}

        /// <summary>
        /// The initialize of the first page.
        /// </summary>
		private void LoadPage1()
		{
			UnvissibleItems(1);
			VissibleItems(0);
            listProperties[0].Label.Visible = false;
            listProperties[0].TextBox.Visible = false;

			if (checkBox.Checked == true) window.ClientSize = new System.Drawing.Size(1150, 600);
			else window.ClientSize = new System.Drawing.Size(680, 600);

			if (listbox.SelectedItem != null)
			{
				AppearModel(listShapes[listbox.SelectedIndex]);
				lbNoStimulus.Visible = false;
			}
			else
			{
				cbAlignmentH.Visible = false;
				cbAlignmentV.Visible = false;
				lbNoStimulus.Visible = true;
				lbNoStimulus.Text = "No stimulus choosen";               
			}

            btPrevious.Visible = false;
			btNext.Visible = false;
			btCreateGraph.Visible = true;
            btRun.Visible = true;
			gbProperties.Visible = true;
			gbStimuli.Visible = true;

            lbTitle.Text = "Sequential experiment guide";
			gbProperties.Text = "Properties";
            lbSubtitle.Text = "Stimuli creating with particular settings";
            lbText.Text = "This page makes possible to create stimuli and set its properties.";
            lbHelpText1.Text = "This page provides tools that allow creating stimuli, set its properties like duration, position and others. When you want to create stimuli you have to choose one of three types of stimuli - Text, Image or Sound type of stimulus. After creating at least one stimulus you can set or change its properties. Finally, you can run experiment. The sequence of running all the stimuli is the same as positions of stimuli in the editing list.";
            lbHelpText2.Text = "1. Choose one of the stimulus type in the drop-down list placed in the Add stimuli panel on the right side of the window.\n\n2. Validate your choice by pressing Add button.\n\n3. Set properties of already added stimuli by selecting stimuli in the list that is placed under the add button.\n\n4. Properties of particular stimuli appear in the Properties panel in the down – right position. If you want to change some stimulus property you have to click on the property textbox and enter its value.\n\n5. You start to run the experiment and create its graph by clicking on the button Run or create its graph by clicking on the button Create.\n ";
		}

        /// <summary>
        /// Connects the dynamic shapes.
        /// </summary>
        /// <param name="entryPoint">The entry point.</param>
        private void ConnectDynamicShapes(Shape entryPoint)
        {
            for (int i = 0; i < listShapes.Count; i++)
            {
                if (i == 0)
                {
                    listTriggers.Add(symbolsCreater.AddTrigger());
                    ConnectTriggShapes(entryPoint, listShapes[i].Shape, 1, 1);
                }
                else
                {
                    listTriggers.Add(symbolsCreater.AddTrigger());
                    ConnectTriggShapes(listShapes[i - 1].Shape, listShapes[i].Shape, 3, 1);
                }
            }
        }

        /// <summary>
        /// Handles the Delete event of the BT control: deletes stimulus on the actual listbox position from the list of shapes and from listbox.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void BT_Delete(object sender, EventArgs e)
		{
			if (listbox.SelectedItem != null)
			{                
				List<TemplatesShape> actualizedList = new List<TemplatesShape>();

				int index = 0;
				foreach (TemplatesShape item in listShapes)
				{
					if (index != listbox.SelectedIndex)
					{
						actualizedList.Add(item);
					}             
					index++;
				}
				listShapes = actualizedList;
				listbox.Items.RemoveAt(listbox.SelectedIndex);
                if (listbox.SelectedItem != null)
                {
                    AppearModel(listShapes[listbox.SelectedIndex]);
                }
                else
                {
                    LoadPage1();
                    if (listShapes.Count == 0)
                    {                       
                        btCreateGraph.Enabled = false;
                        btRun.Enabled = false; 
                    }
                }
			}
		}

        /// <summary>
        /// Handles the Leave event of the TextBoxs control: saves a textboxes content.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void TextBoxs_Leave(object sender, EventArgs e)
		{
			SaveModel(listShapes[listbox.SelectedIndex]);
		}


        /// <summary>
        /// Handles the SelectedIndexChanged event of the CB control: provides an interaction between comboboxes and position textboxes.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void CB_SelectedIndexChanged(object sender, EventArgs e)
		{

			if (cbAlignmentH.Text == "none") listProperties[4].TextBox.Enabled = true;
			else listProperties[4].TextBox.Enabled = false;

			if (cbAlignmentV.Text == "none") listProperties[5].TextBox.Enabled = true;
			else listProperties[5].TextBox.Enabled = false;
		}

        /// <summary>
        /// Handles the Click event of the listbox1 control: appears model data of particular stimulus.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void listbox1_Click(object sender, EventArgs e)
		{
			if (listbox.SelectedItem != null)
			{
				lbNoStimulus.Visible = false;
				int index = listbox.SelectedIndex;
				gbProperties.Text = listbox.SelectedItem.ToString();
				AppearModel(listShapes[listbox.SelectedIndex]);
			}
		}

        /// <summary>
        /// Handles the CheckedChanged event of the CBHelp control: provides appearing of help window.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void CBHelp_CheckedChanged(object sender, EventArgs e)
		{
			if (checkBox.Checked == true) window.ClientSize = new System.Drawing.Size(1150, 600);
			else window.ClientSize = new System.Drawing.Size(680, 600);
		}

        /// <summary>
        /// Adds the static part of a graph. It's fixed part. An user can't change that.
        /// </summary>
		protected override void AddStaticGraphPart()
		{
			//Entry
			Template tempEntry = project.Repository.GetTemplate("EntryPoint");
			Shape shapeEntry = tempEntry.CreateShape();
            shapeEntry.X = shapePossitionX;
			shapeEntry.Y = 400;
            shapePossitionX += 120;
            
			ConnectDynamicShapes(shapeEntry);
			project.Repository.Insert(shapeEntry, diagram);
		}

        /// <summary>
        /// Adds the dynamic part of a graph It's optional part. An user can change this graph part during working with the application.
        /// </summary>
        protected override void AddDynamicGraphPart()
		{
			foreach (TemplatesShape item in listShapes)
			{
                item.Shape.Y = 400;
                item.Shape.X = shapePossitionX;
                shapePossitionX += 120;
				project.Repository.Insert(item.Model);
				project.Repository.Insert(item.Shape, diagram);
			}

			foreach (TemplatesShape item in listTriggers)
			{
				project.Repository.Insert(item.Model);
				project.Repository.Insert(item.Shape, diagram);
			}

			project.Repository.Update();
		}

        /// <summary>
        /// Saves edited properties in textboxes to the model.
        /// </summary>
        /// <param name="templatesShape">The templates shape.</param>
		private void SaveModel(TemplatesShape templatesShape)
		{
			if (templatesShape.Type == "Text")
			{
				SaveTextModel(templatesShape);
			}
			if (templatesShape.Type == "Image")
			{
				SaveImageModel(templatesShape);
			}
			if (templatesShape.Type == "Sound")
			{
				SaveSoundModel(templatesShape);
			}			
		}

        /// <summary>
        /// Saves the text model.
        /// </summary>
        /// <param name="templatesShape">The templates shape.</param>
		private void SaveTextModel(TemplatesShape templatesShape)
		{     
			TextStimulusModel model = (TextStimulusModel)templatesShape.Shape.ModelObject;
            try
            {
                exception = false;
                if (listProperties[0].TextBox.Text != null) model.Duration = Int32.Parse(listProperties[0].TextBox.Text);
                if (listProperties[4].TextBox.Text != null) model.X = Int32.Parse(listProperties[4].TextBox.Text);
                if (listProperties[5].TextBox.Text != null) model.Y = Int32.Parse(listProperties[5].TextBox.Text);
                if (listProperties[6].TextBox.Text != null) model.FontSize = Int32.Parse(listProperties[6].TextBox.Text);
            }
            catch (Exception)
            {
                exception = true;
                MessageBox.Show("Enter only number");
            }			
			model.Text = listProperties[1].TextBox.Text;			
			model.AlignmentHorizontal = cbAlignmentH.Text;
			model.AlignmentVertical = cbAlignmentV.Text;			
		}

        /// <summary>
        /// Saves the image model.
        /// </summary>
        /// <param name="templatesShape">The templates shape.</param>
		private void SaveImageModel(TemplatesShape templatesShape)
		{
            exception = false;
			ImageStimulusModel model = (ImageStimulusModel)templatesShape.Shape.ModelObject;
            try
            {
			    if (listProperties[0].TextBox.Text != null) model.Duration = Int32.Parse(listProperties[0].TextBox.Text);
			    if (listProperties[2].TextBox.Text != null) model.X = Int32.Parse(listProperties[2].TextBox.Text);
			    if (listProperties[3].TextBox.Text != null) model.Y = Int32.Parse(listProperties[3].TextBox.Text);
            }
            catch (Exception)
            {
                exception = true;
                MessageBox.Show("Enter only number");
            }           			

            model.ImagePath = listProperties[1].TextBox.Text;
		}

        /// <summary>
        /// Saves the sound model.
        /// </summary>
        /// <param name="templatesShape">The templates shape.</param>
		private void SaveSoundModel(TemplatesShape templatesShape)
		{
            exception = false;
			SoundStimulusModel model = (SoundStimulusModel)templatesShape.Shape.ModelObject;
            try
            {            			
			    if (listProperties[0].TextBox.Text != null) model.Duration = Int32.Parse(listProperties[0].TextBox.Text);
            }
            catch (Exception)
            {
                exception = true;
                MessageBox.Show("Enter only number");
            }
		}

        /// <summary>
        /// Appears the model that was selected in the listbox.
        /// </summary>
        /// <param name="templatesShape">The templates shape.</param>
		private void AppearModel(TemplatesShape templatesShape)
		{
			if (templatesShape.Type == "Text")
			{
				AppearTextModel(templatesShape);
			}
			if (templatesShape.Type == "Image")
			{
				AppearImageModel(templatesShape);
			}
			if (templatesShape.Type == "Sound")
			{
				AppearSoundModel(templatesShape);
			}
		}

        /// <summary>
        /// Appears the text model.
        /// </summary>
        /// <param name="templatesShape">The templates shape.</param>
		private void AppearTextModel(TemplatesShape templatesShape)
		{
			TextStimulusModel model = (TextStimulusModel)templatesShape.Shape.ModelObject;
            
			listProperties[0].Label.Text = "Duration [ms]";
			listProperties[0].TextBox.Text = model.Duration.ToString();

			listProperties[1].Label.Text = "Text";
			listProperties[1].TextBox.Text = model.Text;

            listProperties[6].Label.Text = "Font size";
            listProperties[6].TextBox.Text = model.FontSize.ToString();

			UnvissibleItems(1);
			VissibleItems(1);
			btPath.Visible = false;

			listProperties[2].Label.Text = "Horizontal position";
			listProperties[3].Label.Text = "Vertical position";

			listProperties[4].Label.Text = "Position X";
			listProperties[4].TextBox.Text = model.X.ToString();

			listProperties[5].Label.Text = "Position Y";
			listProperties[5].TextBox.Text = model.Y.ToString();

			cbAlignmentV.Text = model.AlignmentVertical;
			cbAlignmentH.Text = model.AlignmentHorizontal;

			cbAlignmentH.Visible = true;
			cbAlignmentV.Visible = true;

			listProperties[2].Label.Visible = true;
			listProperties[3].Label.Visible = true;

			listProperties[4].Label.Visible = true;
			listProperties[4].TextBox.Visible = true;

			listProperties[5].Label.Visible = true;
			listProperties[5].TextBox.Visible = true;

            listProperties[6].Label.Visible = true;
            listProperties[6].TextBox.Visible = true;
		}

        /// <summary>
        /// Appears the image model.
        /// </summary>
        /// <param name="templatesShape">The templates shape.</param>
		private void AppearImageModel(TemplatesShape templatesShape)
		{
			ImageStimulusModel model = (ImageStimulusModel)templatesShape.Shape.ModelObject;            
            
			listProperties[0].Label.Text = "Duration [ms]";
			listProperties[0].TextBox.Text = model.Duration.ToString();

			listProperties[1].Label.Text = "ImagePath";
			listProperties[1].TextBox.Text = model.ImagePath;

			listProperties[2].Label.Text = "Position X";
			listProperties[2].TextBox.Text = model.X.ToString();

			listProperties[3].Label.Text = "Position Y";
			listProperties[3].TextBox.Text = model.Y.ToString();

			UnvissibleItems(3);
			VissibleItems(3);       

			btPath.Visible = true;
			cbAlignmentH.Visible = false;
			cbAlignmentV.Visible = false;
		}

        /// <summary>
        /// Appears the sound model.
        /// </summary>
        /// <param name="templatesShape">The templates shape.</param>
		private void AppearSoundModel(TemplatesShape templatesShape)
		{
			SoundStimulusModel model = (SoundStimulusModel)templatesShape.Shape.ModelObject;
            
			listProperties[0].Label.Text = "Duration [ms]";
			listProperties[0].TextBox.Text = model.Duration.ToString();

			UnvissibleItems(1);
			VissibleItems(0);
			btPath.Visible = false;
			cbAlignmentH.Visible = false;
			cbAlignmentV.Visible = false;
		}
	}
}
